package com.seo.textgen.classifier;

import org.apache.commons.lang.StringUtils;

public class CharClassifier {

	private String endOfSentence = ".?!";

	private String punktChars = "-,:;—";

	private String wordPunktChars = "-&'`_";

	private final int[] CHAR_CLASSES = new int[0x10000];

	public CharClassifier() {
		for (int chr = 0; chr < CHAR_CLASSES.length; chr++) {
			int flags = 0;
			if (isLetterInternal(chr)) {
				flags = CharClass.LETTER;
				if (isUpperLetterInternal(chr)) {
					flags |= CharClass.UPPER_LETTER;
				} else {
					flags |= CharClass.LOWER_LETTER;
				}
			} else if (StringUtils.contains(endOfSentence, (char) chr)) {
				flags = CharClass.END_OF_SENTENCE;
			} else if (isDigitInternal(chr)) {
				flags = CharClass.DIGIT;
			} else if (isNewLineInternal(chr)) {
				flags = CharClass.NEW_LINE;
			} else if (isWhitespaceInternal(chr)) {
				flags = CharClass.WHITESPACE;
			} else {
				if (StringUtils.contains(punktChars, (char) chr)) {
					flags = CharClass.PUNCT;
				}
				if (StringUtils.contains(wordPunktChars, (char) chr)) {
					flags |= CharClass.WORD_PUNCT;
				}
			}
			CHAR_CLASSES[chr] = flags;
		}
	}

	private boolean isWhitespaceInternal(int chr) {
		return chr == ' ' || chr == '\t';
	}

	private boolean isNewLineInternal(int chr) {
		return chr == '\n';
	}

	private boolean isDigitInternal(int chr) {
		return Character.isDigit(chr);
	}

	private boolean isUpperLetterInternal(int chr) {
		return Character.isUpperCase(chr);
	}

	private boolean isLetterInternal(int chr) {
		return (chr >= 0x41 && chr <= 0x5A) || (chr >= 0x61 && chr <= 0x7A) || (chr >= 0x400 && chr <= 0x4FF);
	}
	
	public boolean isOther(char chr) {
		return CHAR_CLASSES[chr] == 0;
	}
	
	public boolean isLetter(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.LETTER) != 0;
	}
	
	public boolean isUpperLetter(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.UPPER_LETTER) != 0;
	}
	
	public boolean isLowerLetter(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.LOWER_LETTER) != 0;
	}
	
	public boolean isWordChar(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.WORD_CHAR) != 0;
	}
	
	public boolean isWordStart(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.WORD_START) != 0;
	}
	
	public boolean isDigit(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.DIGIT) != 0;
	}
	
	public boolean isPunkt(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.PUNCT) != 0;
	}
	
	public boolean isWordPunkt(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.WORD_PUNCT) != 0;
	}
	
	public boolean isWhitespace(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.WHITESPACE) != 0;
	}
	
	public boolean isEndOfSentence(char chr) {
		return (CHAR_CLASSES[chr] & CharClass.END_OF_SENTENCE) != 0;
	}
	
	public boolean isNewline(char chr) {
		return chr == '\n';
	}
}
